package com.zhousb.file_retrieval_server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zhousb.file_retrieval_server.domain.bo.RolePermissionBo;
import com.zhousb.file_retrieval_server.domain.entity.SysMenu;
import com.zhousb.file_retrieval_server.domain.entity.SysRole;
import com.zhousb.file_retrieval_server.domain.entity.SysRoleMenu;
import com.zhousb.file_retrieval_server.mapper.SysMenuMapper;
import com.zhousb.file_retrieval_server.mapper.SysRoleMapper;
import com.zhousb.file_retrieval_server.mapper.SysRoleMenuMapper;
import com.zhousb.file_retrieval_server.service.SysRoleService;
import com.zhousb.file_retrieval_server.utils.IdGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.zhousb.file_retrieval_server.common.Constants.SUPER_ADMIN;


/**
 * @author ZhouShenBin
 * @date 2023/12/18 10:16
 * @description
 */

@Service
public class SysRoleServiceImpl implements SysRoleService {

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Override
    public List<SysRole> list() {
        LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ne(SysRole::getRoleCode, SUPER_ADMIN);
        return sysRoleMapper.selectList(queryWrapper);
    }

    @Override
    public boolean create(SysRole sysRole) {
        if (StringUtils.isBlank(sysRole.getRoleCode()) || StringUtils.isBlank(sysRole.getRoleName())) {
            throw new RuntimeException("角色编码或名称不能为空");
        }
        if(sysRole.getRoleCode().equals(SUPER_ADMIN)) {
            throw new RuntimeException("不能创建超级管理员角色");
        }
        sysRole.setId(IdGenerator.nextId());
        sysRoleMapper.insert(sysRole);
        return true;
    }

    @Override
    public boolean delete(Long id) {
        sysRoleMapper.deleteById(id);
        return true;
    }

    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;
    @Resource
    private SysMenuMapper sysMenuMapper;

    @Override
    public List<Long> listPermission(String roleId) {
        List<Long> permissionList = new ArrayList<>();
        LambdaQueryWrapper<SysRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysRoleMenu::getRoleId, roleId);
        List<SysRoleMenu> roleMenus = sysRoleMenuMapper.selectList(queryWrapper);
        roleMenus.forEach(roleMenu -> {
            LambdaQueryWrapper<SysMenu> sysMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysMenuLambdaQueryWrapper.eq(SysMenu::getId, roleMenu.getMenuId())
                    .ne(SysMenu::getParentId, -1);
            SysMenu sysMenu = sysMenuMapper.selectOne(sysMenuLambdaQueryWrapper);
            if (!Objects.isNull(sysMenu)) {
                permissionList.add(sysMenu.getId());
            }
        });
        return permissionList;
    }

    @Override
    public boolean permission(RolePermissionBo bo) {
        List<String> menus = bo.getMenus();
        List<String> finalMenus = new ArrayList<>();
        finalMenus.addAll(menus);
        for (String menuId : menus) {
            SysMenu sysMenu = sysMenuMapper.selectById(Long.valueOf(menuId));
            if (Objects.isNull(sysMenu)) {
                throw new RuntimeException("菜单不存在");
            }
            addParentMenu(finalMenus, sysMenu);
        }
        menus.forEach(menuId -> {
            LambdaQueryWrapper<SysRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysRoleMenu::getRoleId, Long.valueOf(bo.getRoleId()))
                    .eq(SysRoleMenu::getMenuId, Long.valueOf(menuId));
            SysRoleMenu sysRoleMenu = sysRoleMenuMapper.selectOne(queryWrapper);
            if (Objects.isNull(sysRoleMenu)) {
                sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(Long.valueOf(bo.getRoleId()));
                sysRoleMenu.setMenuId(Long.valueOf(menuId));
                sysRoleMenuMapper.insert(sysRoleMenu);
            }
        });

        LambdaQueryWrapper<SysRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysRoleMenu::getRoleId, Long.valueOf(bo.getRoleId()));
        List<SysRoleMenu> roleMenus = sysRoleMenuMapper.selectList(queryWrapper);

        roleMenus.forEach(sysRoleMenu -> {
            if (!finalMenus.contains(sysRoleMenu.getMenuId().toString())) {
                sysRoleMenuMapper.deleteById(sysRoleMenu.getId());
            }
        });
        return true;
    }

    private void addParentMenu(List<String> menus, SysMenu sysMenu) {
        if (!menus.contains(sysMenu.getParentId().toString())) {
            menus.add(sysMenu.getParentId().toString());
            if(sysMenu.getParentId() != -1){
                SysMenu parent = sysMenuMapper.selectById(sysMenu.getParentId());
                addParentMenu(menus, parent);
            }
        }
    }
}
